package com.huanlis.consumer.controller;

import com.huanlis.cloud.utils.R;
import com.huanlis.cloud.utils.ServiceException;
import com.huanlis.consumer.domain.bo.TeacherStudentBo;
import com.huanlis.consumer.domain.entity.RelationshipEntity;
import com.huanlis.consumer.domain.entity.StudentEntity;
import com.huanlis.consumer.feign.client.ProviderFeignClient;
import com.huanlis.consumer.feign.domain.TeacherEntity;
import com.huanlis.consumer.service.RelationshipService;
import com.huanlis.consumer.service.StudentService;
import com.huanlis.consumer.thread.AsyncThread;
import com.huanlis.consumer.thread.LocalCache;
import com.huanlis.consumer.util.LocalState;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.core.Local;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.Objects;
import java.util.concurrent.locks.LockSupport;

@Slf4j
@RestController
@RequestMapping("/async/consumer")
public class AsyncController {

    @Autowired
    private ProviderFeignClient providerFeignClient;

    @Autowired
    private StudentService studentService;

    @Autowired
    private RelationshipService relationshipService;

    public static final String Url = "http://localhost:8002/hello/test/?id=";


    /**
     * 前端调用该接口，该接口通过子线程调用其他的业务服务。LockSupport对子线程和父线程进行阻塞控制。
     * 从而将对前的异步返回变为同步返回。
     *
     * @author lihuan
     * @since 2023/11/3 14:39
     */
    @GetMapping("/async")
    public R testAsync(@RequestParam("id") Integer id) {
        log.info("收到请求：{}----{}", Thread.currentThread().getName(), id);
        LocalCache localCache = new LocalCache();
        localCache.setCache(new LocalState(Url, false, id, ""));
        AsyncThread asyncThread = new AsyncThread(Thread.currentThread(), localCache);
        asyncThread.setName("AsyncThread-"+id);
        asyncThread.start();
        LockSupport.park();
        if (!localCache.getCache().getSuccess()) {
            log.error("异步请求错误：{}----{}", Thread.currentThread().getName(), id);
            return R.success();
        }
        localCache.clear();
        log.info("返回结果：{}----{}", Thread.currentThread().getName(), id);
        return R.success().data(localCache.getCache().getResult());
    }

    @GetMapping("/test")
    public R getTest(@RequestParam("id") Integer id) {
        ResponseEntity<String> test = providerFeignClient.getTest(id);
        if (Objects.isNull(test) || test.getStatusCode().is4xxClientError() || StringUtils.isBlank(test.getBody())) {
            return R.fail();
        }
        return R.success();
    }

    @PostMapping("/save")
    @GlobalTransactional
    @Transactional(rollbackFor = Exception.class)
    public R save(@RequestBody TeacherStudentBo teacherStudentBo) {
        StudentEntity studentEntity = new StudentEntity();
        studentEntity.setName(teacherStudentBo.getStudentName());
        studentEntity.setAge(teacherStudentBo.getStudentAge());
        studentEntity.setGender(teacherStudentBo.getStudentGender());
        studentEntity.setCreateTime(LocalDateTime.now());
        boolean save = studentService.save(studentEntity);
        if (!save) {
            log.error("学生数据写入失败");
            throw new ServiceException(4000, "学生数据写入失败");
        }
        TeacherEntity teacherEntity = new TeacherEntity();
        teacherEntity.setName(teacherStudentBo.getTeacherName());
        teacherEntity.setAge(teacherStudentBo.getTeacherAge());
        teacherEntity.setGender(teacherStudentBo.getTeacherGender());
        R r = providerFeignClient.saveTeacher(teacherEntity);
        if (!r.getSuccess()) {
            log.error("教师数据写入失败");
            throw new ServiceException(4000, "教师数据写入失败");
        }
        RelationshipEntity relationshipEntity = new RelationshipEntity();
        relationshipEntity.setStudentId(studentEntity.getId());
        relationshipEntity.setTeacherId(((TeacherEntity)r.getData()).getId());
        relationshipEntity.setCreateTime(LocalDateTime.now());
        boolean saveRelationship = relationshipService.save(relationshipEntity);
        return saveRelationship ? R.success() : R.fail();
    }

}
